/*
 * MainWindow.java
 *
 * Created on January 17, 2009, 1:39 PM
 */
package javapoptools;

import com.novusradix.JavaPop.Client.ModelData;
import com.sun.opengl.util.Animator;
import java.awt.Color;
import java.awt.Dimension;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.prefs.Preferences;
import javax.media.opengl.GLCapabilities;
import javax.swing.JFileChooser;
import javax.swing.filechooser.FileFilter;

/**
 *
 * @author  mom
 */
public class MainWindow extends javax.swing.JFrame {

    PreviewPanel mp;
    final JFileChooser chooser;
    Color playerColor = Color.RED;
    private String modelName;

    /** Creates new form MainWindow */
    public MainWindow() {
        initComponents();
        chooser = new JFileChooser();
        GLCapabilities caps = new GLCapabilities();
        caps.setSampleBuffers(true);
        caps.setNumSamples(4);
        mp = new PreviewPanel(caps, this);


        mp.setPreferredSize(new Dimension(128, 128));
        previewPanel.add(mp);

        XImporter i = new XImporter(getClass().getResource("/com/novusradix/JavaPop/models/peon5.model"));
        vertexEditor.setText(loadText(getClass().getResource("/com/novusradix/JavaPop/Client/Shaders/ModelVertex.shader")));
        fragmentEditor.setText(loadText(getClass().getResource("/com/novusradix/JavaPop/Client/Shaders/ModelFragment.shader")));
        modelName = "peon5";
        mp.setData(i.getModel());
        Animator a = new Animator(mp);
        a.start();
    }

    private String loadText(URL u) {
        try {
            BufferedReader br;
            StringBuffer sb;

            br = new BufferedReader(new InputStreamReader(u.openStream()));

            sb = new StringBuffer();
            char[] buffer = new char[1024];
            int count;
            do {
                count = br.read(buffer);
                if (count > 0) {
                    sb.append(buffer, 0, count);
                }
            } while (count > 0);
            return sb.toString();
        } catch (IOException ex) {
            Logger.getLogger(MainWindow.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }

    public void setStatus(String s) {
        status.setText(s);
    }

    public void appendStatus(String s) {
        status.append(s);
    }

    public boolean isVertexShaderEnabled() {
        return vertexOnOff.isSelected();
    }

    public boolean isFragmentShaderEnabled() {
        return fragmentOnOff.isSelected();
    }

    public String getVertexShader() {
        return vertexEditor.getText();
    }

    public String getFragmentShader() {
        return fragmentEditor.getText();
    }

    public float getRed() {
        return redSlider.getValue() / 256.0f;
    }

    public float getGreen() {
        return greenSlider.getValue() / 256.0f;
    }

    public float getBlue() {
        return blueSlider.getValue() / 256.0f;
    }

    public float getAlpha() {
        return alphaSlider.getValue() / 256.0f;
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        renderGroup = new javax.swing.ButtonGroup();
        optionPanel = new javax.swing.JPanel();
        panelZoom = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        jSlider1 = new javax.swing.JSlider();
        panelColour = new javax.swing.JPanel();
        jLabel3 = new javax.swing.JLabel();
        jPanel1 = new javax.swing.JPanel();
        jLabel4 = new javax.swing.JLabel();
        redSlider = new javax.swing.JSlider();
        jPanel2 = new javax.swing.JPanel();
        jLabel5 = new javax.swing.JLabel();
        greenSlider = new javax.swing.JSlider();
        jPanel3 = new javax.swing.JPanel();
        jLabel6 = new javax.swing.JLabel();
        blueSlider = new javax.swing.JSlider();
        jPanel4 = new javax.swing.JPanel();
        jLabel7 = new javax.swing.JLabel();
        alphaSlider = new javax.swing.JSlider();
        panelRender = new javax.swing.JPanel();
        jLabel2 = new javax.swing.JLabel();
        renderFixedFunction = new javax.swing.JRadioButton();
        renderDefault = new javax.swing.JRadioButton();
        renderCustom = new javax.swing.JRadioButton();
        previewPanel = new javax.swing.JPanel();
        editors = new javax.swing.JPanel();
        jSplitPane1 = new javax.swing.JSplitPane();
        jSplitPane2 = new javax.swing.JSplitPane();
        vertexPane = new javax.swing.JPanel();
        vertexOnOff = new javax.swing.JToggleButton();
        jScrollPane2 = new javax.swing.JScrollPane();
        vertexEditor = new javax.swing.JEditorPane();
        fragmentPane = new javax.swing.JPanel();
        fragmentOnOff = new javax.swing.JToggleButton();
        jScrollPane3 = new javax.swing.JScrollPane();
        fragmentEditor = new javax.swing.JEditorPane();
        jScrollPane1 = new javax.swing.JScrollPane();
        status = new javax.swing.JTextArea();
        Menu1 = new javax.swing.JMenuBar();
        FileMenu1 = new javax.swing.JMenu();
        OpenModel = new javax.swing.JMenuItem();
        SaveModel = new javax.swing.JMenuItem();
        jMenu3 = new javax.swing.JMenu();
        OpenTexture = new javax.swing.JMenuItem();
        jMenu1 = new javax.swing.JMenu();
        OpenVertex = new javax.swing.JMenuItem();
        OpenFragment = new javax.swing.JMenuItem();
        SaveVertex = new javax.swing.JMenuItem();
        SaveFragment = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setName("JavaPop tools"); // NOI18N

        optionPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Options"));
        optionPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT));

        panelZoom.setMinimumSize(new java.awt.Dimension(120, 54));
        panelZoom.setPreferredSize(new java.awt.Dimension(120, 70));
        panelZoom.setRequestFocusEnabled(false);
        panelZoom.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 0, 0));

        jLabel1.setText("Zoom");
        panelZoom.add(jLabel1);

        jSlider1.setMajorTickSpacing(1);
        jSlider1.setMaximum(4);
        jSlider1.setMinimum(1);
        jSlider1.setPaintLabels(true);
        jSlider1.setPaintTicks(true);
        jSlider1.setSnapToTicks(true);
        jSlider1.setValue(1);
        jSlider1.setPreferredSize(new java.awt.Dimension(113, 54));
        jSlider1.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                jSlider1StateChanged(evt);
            }
        });
        panelZoom.add(jSlider1);

        optionPanel.add(panelZoom);

        panelColour.setMinimumSize(new java.awt.Dimension(120, 100));
        panelColour.setPreferredSize(new java.awt.Dimension(120, 180));
        panelColour.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 0, 0));

        jLabel3.setText("Player colour");
        panelColour.add(jLabel3);

        jLabel4.setText("R");
        jPanel1.add(jLabel4);

        redSlider.setMajorTickSpacing(32);
        redSlider.setMaximum(256);
        redSlider.setPaintTicks(true);
        redSlider.setValue(256);
        redSlider.setName(""); // NOI18N
        redSlider.setPreferredSize(new java.awt.Dimension(100, 30));
        jPanel1.add(redSlider);

        panelColour.add(jPanel1);

        jLabel5.setText("G");
        jPanel2.add(jLabel5);

        greenSlider.setMajorTickSpacing(32);
        greenSlider.setMaximum(256);
        greenSlider.setPaintTicks(true);
        greenSlider.setName(""); // NOI18N
        greenSlider.setPreferredSize(new java.awt.Dimension(100, 30));
        jPanel2.add(greenSlider);

        panelColour.add(jPanel2);

        jLabel6.setText("B");
        jPanel3.add(jLabel6);

        blueSlider.setMajorTickSpacing(32);
        blueSlider.setMaximum(256);
        blueSlider.setPaintTicks(true);
        blueSlider.setName(""); // NOI18N
        blueSlider.setPreferredSize(new java.awt.Dimension(100, 30));
        jPanel3.add(blueSlider);

        panelColour.add(jPanel3);

        jLabel7.setText("A");
        jPanel4.add(jLabel7);

        alphaSlider.setMajorTickSpacing(32);
        alphaSlider.setMaximum(256);
        alphaSlider.setPaintTicks(true);
        alphaSlider.setValue(256);
        alphaSlider.setName(""); // NOI18N
        alphaSlider.setPreferredSize(new java.awt.Dimension(100, 30));
        jPanel4.add(alphaSlider);

        panelColour.add(jPanel4);

        optionPanel.add(panelColour);

        panelRender.setMaximumSize(new java.awt.Dimension(140, 100));
        panelRender.setMinimumSize(new java.awt.Dimension(140, 100));
        panelRender.setPreferredSize(new java.awt.Dimension(130, 90));
        panelRender.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 5, 0));

        jLabel2.setText("Rendering");
        panelRender.add(jLabel2);

        renderGroup.add(renderFixedFunction);
        renderFixedFunction.setLabel("Fixed Function");
        renderFixedFunction.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                renderFixedFunctionActionPerformed(evt);
            }
        });
        panelRender.add(renderFixedFunction);

        renderGroup.add(renderDefault);
        renderDefault.setLabel("Model default");
        renderDefault.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                renderDefaultActionPerformed(evt);
            }
        });
        panelRender.add(renderDefault);

        renderGroup.add(renderCustom);
        renderCustom.setSelected(true);
        renderCustom.setText("Custom");
        renderCustom.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                renderCustomActionPerformed(evt);
            }
        });
        panelRender.add(renderCustom);

        optionPanel.add(panelRender);

        previewPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Preview"));

        editors.setLayout(new java.awt.BorderLayout());

        jSplitPane1.setDividerLocation(399);
        jSplitPane1.setDividerSize(4);
        jSplitPane1.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
        jSplitPane1.setResizeWeight(1.0);

        jSplitPane2.setDividerLocation(300);
        jSplitPane2.setResizeWeight(0.5);
        jSplitPane2.addComponentListener(new java.awt.event.ComponentAdapter() {
            public void componentResized(java.awt.event.ComponentEvent evt) {
                jSplitPane2ComponentResized(evt);
            }
        });

        vertexPane.setLayout(new javax.swing.BoxLayout(vertexPane, javax.swing.BoxLayout.PAGE_AXIS));

        vertexOnOff.setSelected(true);
        vertexOnOff.setText("Vertex shader enabled");
        vertexPane.add(vertexOnOff);

        jScrollPane2.setViewportView(vertexEditor);

        vertexPane.add(jScrollPane2);

        jSplitPane2.setLeftComponent(vertexPane);

        fragmentPane.setLayout(new javax.swing.BoxLayout(fragmentPane, javax.swing.BoxLayout.PAGE_AXIS));

        fragmentOnOff.setSelected(true);
        fragmentOnOff.setText("Fragment shader enabled");
        fragmentPane.add(fragmentOnOff);

        jScrollPane3.setViewportView(fragmentEditor);

        fragmentPane.add(jScrollPane3);

        jSplitPane2.setRightComponent(fragmentPane);

        jSplitPane1.setLeftComponent(jSplitPane2);

        status.setColumns(20);
        status.setRows(5);
        jScrollPane1.setViewportView(status);

        jSplitPane1.setRightComponent(jScrollPane1);

        editors.add(jSplitPane1, java.awt.BorderLayout.CENTER);

        FileMenu1.setText("Model");

        OpenModel.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_O, java.awt.event.InputEvent.META_MASK));
        OpenModel.setText("Open Model...");
        OpenModel.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                OpenMenuItemActionPerformed(evt);
            }
        });
        FileMenu1.add(OpenModel);

        SaveModel.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S, java.awt.event.InputEvent.META_MASK));
        SaveModel.setText("Save Model As...");
        SaveModel.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                SaveModelActionPerformed(evt);
            }
        });
        FileMenu1.add(SaveModel);

        Menu1.add(FileMenu1);

        jMenu3.setText("Texture");

        OpenTexture.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_T, java.awt.event.InputEvent.META_MASK));
        OpenTexture.setText("Open Texture...");
        OpenTexture.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                openTextureMenuItemActionPerformed(evt);
            }
        });
        jMenu3.add(OpenTexture);

        Menu1.add(jMenu3);

        jMenu1.setText("Menu");

        OpenVertex.setText("Open Vertex Shader");
        jMenu1.add(OpenVertex);

        OpenFragment.setText("Open Fragment Shader");
        jMenu1.add(OpenFragment);

        SaveVertex.setText("Save Vertex Shader");
        jMenu1.add(SaveVertex);

        SaveFragment.setText("Save Fragment Shader");
        jMenu1.add(SaveFragment);

        Menu1.add(jMenu1);

        setJMenuBar(Menu1);

        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING, false)
                    .add(org.jdesktop.layout.GroupLayout.LEADING, previewPanel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .add(org.jdesktop.layout.GroupLayout.LEADING, optionPanel, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 145, Short.MAX_VALUE))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(editors, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 637, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .add(previewPanel, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 166, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(optionPanel, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 381, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(44, Short.MAX_VALUE))
            .add(editors, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 591, Short.MAX_VALUE)
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

private void OpenMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_OpenMenuItemActionPerformed
    Preferences p = Preferences.userNodeForPackage(this.getClass());
    String dir = p.get("ModelDir", null);
    if (dir != null) {
        chooser.setCurrentDirectory(new File(dir));
    }
    chooser.setDialogTitle("Open Model");
    chooser.setFileFilter(null);
    chooser.resetChoosableFileFilters();
    FileFilter ffAll,ffX ,ffModel ;
    ffAll = FileFilterFactory.getFilter("All models", new String[]{"x", "model"});
    ffX = FileFilterFactory.getFilter("DirectX Models", new String[]{"x"});
    ffModel = FileFilterFactory.getFilter("JavaPop Models", new String[]{"model"});
    chooser.addChoosableFileFilter(ffAll);
    chooser.addChoosableFileFilter(ffX);
    chooser.addChoosableFileFilter(ffModel);
    chooser.setFileFilter(ffAll);
    int returnVal = chooser.showOpenDialog(this);
    if (returnVal == JFileChooser.APPROVE_OPTION) {
        File f = chooser.getSelectedFile();
        p.put("ModelDir", f.getParent());
        String ext = FileFilterFactory.getExtension(f);
        modelName = f.getName();
        modelName = modelName.substring(0, modelName.length() - ext.length() - 1);
        if (ext.equals("x")) {

            XImporter i;
            try {
                i = new XImporter(f.toURL());
                mp.setData(i.getModel());
            } catch (MalformedURLException ex) {
                Logger.getLogger(MainWindow.class.getName()).log(Level.SEVERE, null, ex);
            }
        } else if (ext.equals("model")) {
            try {
                ModelData md = ModelData.fromURL(f.toURL());
                mp.setData(md);
            } catch (IOException ex) {
                Logger.getLogger(MainWindow.class.getName()).log(Level.SEVERE, null, ex);
            }


        }
    }
}//GEN-LAST:event_OpenMenuItemActionPerformed

private void jSlider1StateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_jSlider1StateChanged
    mp.setZoom(jSlider1.getValue());
}//GEN-LAST:event_jSlider1StateChanged

private void openTextureMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openTextureMenuItemActionPerformed

    Preferences p = Preferences.userNodeForPackage(this.getClass());
    String dir = p.get("TextureDir", null);
    if (dir != null) {
        chooser.setCurrentDirectory(new File(dir));
    }
    chooser.setDialogTitle("Open Texture");
    chooser.resetChoosableFileFilters();
    chooser.setFileFilter(FileFilterFactory.getFilter("PNG images", new String[]{"png"}));
    int returnVal = chooser.showOpenDialog(this);
    if (returnVal == JFileChooser.APPROVE_OPTION) {
        File f = chooser.getSelectedFile();
        p.put("TextureDir", f.getParent());
        try {
            mp.setTexture(f.toURL());
        } catch (MalformedURLException ex) {
            Logger.getLogger(MainWindow.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

}//GEN-LAST:event_openTextureMenuItemActionPerformed

private void renderFixedFunctionActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_renderFixedFunctionActionPerformed
    mp.setPipeline(PreviewPanel.Pipeline.FIXED);
}//GEN-LAST:event_renderFixedFunctionActionPerformed

private void renderDefaultActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_renderDefaultActionPerformed
    mp.setPipeline(PreviewPanel.Pipeline.DEFAULT);

}//GEN-LAST:event_renderDefaultActionPerformed

private void renderCustomActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_renderCustomActionPerformed
    mp.setPipeline(PreviewPanel.Pipeline.CUSTOM);

}//GEN-LAST:event_renderCustomActionPerformed

private void jSplitPane2ComponentResized(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_jSplitPane2ComponentResized
}//GEN-LAST:event_jSplitPane2ComponentResized

private void SaveModelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_SaveModelActionPerformed
    Preferences p = Preferences.userNodeForPackage(this.getClass());
    String dir = p.get("ModelSaveDir", null);
    if (dir != null) {
        chooser.setCurrentDirectory(new File(dir));
    }
    chooser.setDialogTitle("Save Model");
    chooser.resetChoosableFileFilters();
    chooser.setFileFilter(FileFilterFactory.getFilter("Model Files", new String[]{"model"}));
    chooser.setSelectedFile(new File(modelName.concat(".model")));
    int returnVal = chooser.showSaveDialog(this);
    ObjectOutputStream oo;
    if (returnVal == JFileChooser.APPROVE_OPTION) {
        File f = chooser.getSelectedFile();
        p.put("ModelSaveDir", f.getParent());

        try {
            oo = new ObjectOutputStream(new FileOutputStream(f));
            oo.writeObject(mp.getModelData());
            oo.close();
        } catch (IOException ex) {
            Logger.getLogger(MainWindow.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}//GEN-LAST:event_SaveModelActionPerformed
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JMenu FileMenu1;
    private javax.swing.JMenuBar Menu1;
    private javax.swing.JMenuItem OpenFragment;
    private javax.swing.JMenuItem OpenModel;
    private javax.swing.JMenuItem OpenTexture;
    private javax.swing.JMenuItem OpenVertex;
    private javax.swing.JMenuItem SaveFragment;
    private javax.swing.JMenuItem SaveModel;
    private javax.swing.JMenuItem SaveVertex;
    private javax.swing.JSlider alphaSlider;
    private javax.swing.JSlider blueSlider;
    private javax.swing.JPanel editors;
    private javax.swing.JEditorPane fragmentEditor;
    private javax.swing.JToggleButton fragmentOnOff;
    private javax.swing.JPanel fragmentPane;
    private javax.swing.JSlider greenSlider;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JMenu jMenu1;
    private javax.swing.JMenu jMenu3;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JPanel jPanel4;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JSlider jSlider1;
    private javax.swing.JSplitPane jSplitPane1;
    private javax.swing.JSplitPane jSplitPane2;
    private javax.swing.JPanel optionPanel;
    private javax.swing.JPanel panelColour;
    private javax.swing.JPanel panelRender;
    private javax.swing.JPanel panelZoom;
    private javax.swing.JPanel previewPanel;
    private javax.swing.JSlider redSlider;
    private javax.swing.JRadioButton renderCustom;
    private javax.swing.JRadioButton renderDefault;
    private javax.swing.JRadioButton renderFixedFunction;
    private javax.swing.ButtonGroup renderGroup;
    private javax.swing.JTextArea status;
    private javax.swing.JEditorPane vertexEditor;
    private javax.swing.JToggleButton vertexOnOff;
    private javax.swing.JPanel vertexPane;
    // End of variables declaration//GEN-END:variables
}
